package org.infinitest.intellij;

import org.apache.log4j.Logger;
import org.infinitest.InfinitestBuilder;
import org.infinitest.InfinitestCoreBuilder;
import static org.infinitest.intellij.idea.window.InfinitestToolWindowComponent.TOOL_WINDOW_ID;
import org.infinitest.intellij.idea.IdeaCompilationListener;
import org.infinitest.swingui.SwingEventQueue;

import javax.swing.*;
import java.awt.*;

public class InfinitestRunner implements Runnable {
  private ModuleSettings moduleSettings;
  private ToolWindowRegistry toolWindowRegistry;
  private CompilationNotifier compilationNotifier;
  private ProjectCompiler compiler;
  private InfinitestAnnotatorLocator annotatorLoator;
  private InfinitestBuilder infinitestBuilder;
  private IdeaCompilationListener testControl;

  public InfinitestRunner(ModuleSettings moduleSettings, ToolWindowRegistry toolWindowRegistry,
                          CompilationNotifier compilationNotifier, ProjectCompiler compiler,
                          InfinitestAnnotatorLocator annotatorLoator) {
    this.moduleSettings = moduleSettings;
    this.toolWindowRegistry = toolWindowRegistry;
    this.compilationNotifier = compilationNotifier;
    this.compiler = compiler;
    this.annotatorLoator = annotatorLoator;
    this.infinitestBuilder = createInfinitestBuilder();
  }

  public void run() {
    moduleSettings.writeToLogger(Logger.getLogger(getClass()));
    
    testControl = new IdeaCompilationListener(infinitestBuilder.getCore(), moduleSettings);
    registerInfinitestWindow();
    addCompilationStatusListener();
    addTestEventStatusListener();
    forceProjectRebuild();
  }

  private void forceProjectRebuild() {
    compiler.forceRebuild();
  }

  private void addCompilationStatusListener() {
    compilationNotifier.addCompilationStatusListener(testControl);
  }

  private void addTestEventStatusListener() {
    infinitestBuilder.getCore().addTestStatusListener(
            new InfinitestTestStatusListener(annotatorLoator.findInfinitestAnnotator()));
  }

  private void registerInfinitestWindow() {
    JPanel rootPanel = new JPanel(new BorderLayout());

    rootPanel.add(infinitestBuilder.createPluginComponent(testControl), BorderLayout.CENTER);

    toolWindowRegistry.registerToolWindow(rootPanel, toolWindowId());
  }

  public void stop() {
    toolWindowRegistry.unregisterToolWindow(toolWindowId());
  }

  private String toolWindowId() {
    return TOOL_WINDOW_ID + "_" + moduleSettings.getName();
  }

  private InfinitestBuilder createInfinitestBuilder() {
    InfinitestCoreBuilder coreBuilder = new InfinitestCoreBuilder(moduleSettings.getRuntimeEnvironment(), new SwingEventQueue());
    return new InfinitestBuilder(coreBuilder.createCore());
  }
}
